package org.springblade.modules.admin.task;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;
import org.springblade.common.utils.message.MessageCenterUtils;
import org.springblade.common.utils.message.domain.MessageParam;
import org.springblade.common.utils.message.domain.SendRequest;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.constant.BladeConstant;
import org.springblade.core.tool.utils.Func;
import org.springblade.modules.admin.dto.ElevatorPlanUserDTO;
import org.springblade.modules.admin.entity.MaintainMsg;
import org.springblade.modules.admin.entity.MaintainPlanContent;
import org.springblade.modules.admin.entity.MaintainPlanContentExt;
import org.springblade.modules.admin.entity.UserExt;
import org.springblade.modules.admin.enums.TaskStatusEnum;
import org.springblade.modules.admin.service.*;
import org.springblade.modules.admin.vo.MaintainPlanConfigVO;
import org.springblade.modules.admin.vo.UserExtVO;
import org.springblade.modules.system.entity.Tenant;
import org.springblade.modules.system.entity.User;
import org.springblade.modules.system.service.ITenantService;
import org.springblade.modules.system.service.IUserService;
import org.springblade.modules.system.vo.SimpleUserVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author zcc
 * @version 1.0
 * @date 2022/4/22 16:20
 */
@Slf4j
@Component
public class PlanContentJob {

	@Resource
	private IMaintainPlanContentService maintainPlanContentService;

	@Resource
	private IMaintainPlanContentExtService maintainPlanContentExtService;

	@Resource
	private MaintainMsgService msgService;

	@Resource
	private IUserService userService;

	@Resource
	private MessageCenterUtils messageCenterUtils;

	@Resource
	private MaintainAbarbeitungService abarbeitungService;
	@Resource
	private ITenantService tenantService;
	@Resource
	private IMaintainPlanConfigService planConfigService;
	@Resource
	private Environment environment;

	/**
	 * 每天更新工单逾期的天数
	 */
	//@Scheduled(cron = "0 1 0 * * ?")
	@XxlJob(value = "updatePlanContentStatus")
	private void updatePlanContentStatus() {

		XxlJobHelper.handleSuccess("每天更新工单逾期-(updatePlanContentStatus)-[执行]开始");

		try {
			DateTime beginTime = DateUtil.beginOfDay(DateUtil.offsetDay(new Date(), -2));
			DateTime endTime = DateUtil.endOfDay(DateUtil.yesterday());
			List<MaintainPlanContent> list = maintainPlanContentService.list(Wrappers.<MaintainPlanContent>lambdaQuery().between(MaintainPlanContent::getPlanDate, beginTime, endTime).ne(MaintainPlanContent::getStatus, TaskStatusEnum.BY_SIGN.getStatus()).ne(MaintainPlanContent::getStatus, TaskStatusEnum.BY_MAINTAIN_SIGN.getStatus()));
			if (list.size() > 0) {
				List<Long> ids = list.stream().map(MaintainPlanContent::getId).collect(Collectors.toList());
				List<MaintainPlanContentExt> list1 = maintainPlanContentExtService.list(Wrappers.<MaintainPlanContentExt>lambdaQuery().in(MaintainPlanContentExt::getPlanId, ids));
				for (MaintainPlanContentExt maintainPlanContentExt : list1) {
					maintainPlanContentExt.setOverdueDay(1);
				}
				maintainPlanContentExtService.updateBatchById(list1);
			}
			XxlJobHelper.handleSuccess("每天更新工单逾期-(updatePlanContentStatus)-[执行]成功");
		} catch (Exception e) {
			XxlJobHelper.handleSuccess("每天更新工单逾期-(updatePlanContentStatus)-[执行]失败" + e);
		}

	}

	/**
	 * 每天更新工单逾期的标签
	 */
	//@Scheduled(cron = "0 0 1 * * ?")
	@XxlJob(value = "updatePlanContentOverdueType")
	public void updatePlanContentOverdueType() {

		XxlJobHelper.handleSuccess("每天更新工单逾期-(updatePlanContentOverdueType)-[执行]开始");

		try {
			// 保养工单
			List<MaintainPlanContentExt> planList = maintainPlanContentExtService.listAllUnfinishedByPlan();
			Date date = DateUtil.parseDate(DateUtil.today());
			if(Func.isNotEmpty(planList)){
				planList.forEach(e -> {
					if(Func.isNotEmpty(e.getOverdueDate())){
						// 未逾期
						if(date.getTime() < e.getOverdueDate().getTime()){
							e.setOverdueType(1);
						}
						// 明天即将逾期
						if(date.getTime() == e.getOverdueDate().getTime()){
							e.setOverdueType(2);
						}
						// 已逾期
						if(date.getTime() > e.getOverdueDate().getTime()){
							e.setOverdueType(3);
						}
					}
				});
				maintainPlanContentExtService.updateBatchById(planList);
			}

			// 整改工单
			List<Tenant> tenantList = tenantService.list();
			tenantList.forEach(e -> {
				abarbeitungService.updateZgPlanOverdueType(e.getTenantId());
			});
			XxlJobHelper.handleSuccess("每天更新工单逾期-(updatePlanContentOverdueType)-[执行]成功");
		} catch (Exception e) {
			XxlJobHelper.handleSuccess("每天更新工单逾期-(updatePlanContentOverdueType)-[执行]失败" + e);
		}

	}

	/**
	 * 每天统计用户未签字
	 */
	//@Scheduled(cron = "0 0 18,20 * * ?")
	@XxlJob(value = "countByPlanUserSignature")
	public void countByPlanUserSignature() {

		XxlJobHelper.handleSuccess("每天统计用户未签字-(countByPlanUserSignature)-[执行]开始");

		try {
			List<Tenant> tenantList = tenantService.list();
			tenantList.forEach(t -> {
				List<ElevatorPlanUserDTO> planUserDTOS = maintainPlanContentService.selectCountByPlanUserSignature(t.getTenantId());
				if(Func.isNotEmpty(planUserDTOS)){
					planUserDTOS = planUserDTOS.stream().filter(e -> e.getSignatureCount() == 0).collect(Collectors.toList());
					if(Func.isNotEmpty(planUserDTOS)){
						Map<Long,List<ElevatorPlanUserDTO>> map = planUserDTOS.stream().filter(e -> Func.isNotEmpty(e.getUserId())).collect(Collectors.groupingBy(ElevatorPlanUserDTO::getUserId));
						map.forEach((k,v) -> {
							SimpleUserVO userVO = userService.getSimpleUserInfo(k);
							Integer count = v.size();
							if(count > 0){
								Map<String, String> contentMap = new HashMap<>(4);
								contentMap.put("title", "本人未维保签字通知");
								contentMap.put("content", String.format("你有%s个年审梯保养未完成维保签字，请及时跟进",count));
								contentMap.put(BladeConstant.MDC_TENANT_ID_KEY, t.getTenantId());
								SendRequest request = SendRequest.builder()
									.messageTemplateId("1902653899365752834")
									.messageParam(
										MessageParam.builder()
											.receiver(String.valueOf(userVO.getUserId()))
											.variables(contentMap)
											.build()
									).build();
								R r = messageCenterUtils.sendMessage(request);
								log.info("梯无忧PC推送结果:" + JSON.toJSONString(r));

								if(Func.isNotEmpty(userVO.getOpenid())){
									contentMap = new HashMap<>(4);
									contentMap.put("phrase4", "保养");
									contentMap.put("phrase5", "本人未签字");
									contentMap.put("character_string42", String.valueOf(count));
									contentMap.put("time10", DateUtil.now());
									// 构造消息
									String url = "/subpages/workOrders/records?type=2&tabIndex=0&statusStr=3&auditTypeStr=2&userSignatureType=1";
									Map<String, String> variablesMap = new HashMap<>(4);
									variablesMap.put("content", JSONObject.toJSONString(contentMap));
									variablesMap.put("url", url);
									variablesMap.put(BladeConstant.MDC_TENANT_ID_KEY, t.getTenantId());
									// 维保小程序appid
									variablesMap.put("miniProgramId", "wxb8dc0f5451620604");

									SendRequest sendRequest = SendRequest.builder()
										.messageTemplateId("1902892272744779777")
										.messageParam(MessageParam.builder()
											.receiver(String.valueOf(userVO.getOpenid()))
											.variables(variablesMap)
											.build())
										.build();
									r = messageCenterUtils.sendMessage(sendRequest);
									log.info("公众号推送结果:" + JSON.toJSONString(r));
								}

								if(Func.isNotEmpty(userVO.getRegistrationId())){
									contentMap = new HashMap<>(4);
									contentMap.put("title", "维保未签字通知");
									contentMap.put("content", String.format("你有%s个年审梯保养未完成维保签字，请及时跟进",count));
									contentMap.put("url", "/subpages/workorders/records?type=2&tabIndex=0&statusStr=3&auditTypeStr=2&userSignatureType=1");
									contentMap.put(BladeConstant.MDC_TENANT_ID_KEY, t.getTenantId());
									request = SendRequest.builder()
										.messageTemplateId("1902915055486881794")
										.messageParam(
											MessageParam.builder()
												.receiver(String.valueOf(userVO.getRegistrationId()))
												.variables(contentMap)
												.build()
										).build();
									r = messageCenterUtils.sendMessage(request);
									log.info("APP推送结果:" + JSON.toJSONString(r));
								}
							}
						});
					}
				}
			});
			XxlJobHelper.handleSuccess("每天统计用户未签字-(countByPlanUserSignature)-[执行]成功");
		} catch (Exception e) {
			XxlJobHelper.handleSuccess("每天统计用户未签字-(countByPlanUserSignature)-[执行]失败" + e);
		}

	}

	/**
	 * 每天统计用户保养逾期数量发送通知
	 */
	//@Scheduled(cron = "0 0 9,15,20 * * ?")
	@XxlJob(value = "countUserByPlanOverdue")
	public void countUserByPlanOverdue() {

		XxlJobHelper.handleSuccess("每天统计用户保养逾期数量发送通知-(countUserByPlanOverdue)-[执行]开始");

		try {
			List<Tenant> tenantList = tenantService.list();
			tenantList.forEach(t -> {
				List<ElevatorPlanUserDTO> planUserDTOS = maintainPlanContentService.selectCountUserByPlanOverdue(t.getTenantId());
				if(Func.isNotEmpty(planUserDTOS)){
					// 已逾期
					List<ElevatorPlanUserDTO> v3 = planUserDTOS.stream().filter(e -> Func.isNotEmpty(e.getUserId()) &&  Func.isNotEmpty(e.getOverdueType()) && e.getOverdueType() == 3).collect(Collectors.toList());
					if(Func.isNotEmpty(planUserDTOS)){
						Map<Long,List<ElevatorPlanUserDTO>> map = v3.stream().collect(Collectors.groupingBy(ElevatorPlanUserDTO::getUserId));
						map.forEach((k,v) -> {
							SimpleUserVO userVO = userService.getSimpleUserInfo(k);
							Integer count = v.size();
							if(count > 0){
								Map<String, String> contentMap = new HashMap<>(4);
								contentMap.put("title", "保养未完成，已逾期");
								contentMap.put("content", String.format("你有%s个年审梯保养未完成且已逾期，请及时跟进",count));
								contentMap.put(BladeConstant.MDC_TENANT_ID_KEY, t.getTenantId());
								SendRequest request = SendRequest.builder()
									.messageTemplateId("1902653899365752834")
									.messageParam(
										MessageParam.builder()
											.receiver(String.valueOf(userVO.getUserId()))
											.variables(contentMap)
											.build()
									).build();
								R r = messageCenterUtils.sendMessage(request);
								log.info("梯无忧PC推送结果:" + JSON.toJSONString(r));

								if(Func.isNotEmpty(userVO.getOpenid())){
									contentMap = new HashMap<>(4);
									contentMap.put("phrase4", "保养");
									contentMap.put("phrase5", "已逾期");
									contentMap.put("character_string42", String.valueOf(count));
									contentMap.put("time10", DateUtil.now());
									// 构造消息
									String url = "/subpages/workOrders/records?type=2&tabIndex=0&statusStr=1,2,3&overdueTypeStr=3&auditTypeStr=2";
									Map<String, String> variablesMap = new HashMap<>(4);
									variablesMap.put("content", JSONObject.toJSONString(contentMap));
									variablesMap.put("url", url);
									variablesMap.put(BladeConstant.MDC_TENANT_ID_KEY, t.getTenantId());
									// 维保小程序appid
									variablesMap.put("miniProgramId", "wxb8dc0f5451620604");
									request = SendRequest.builder()
										.messageTemplateId("1902892272744779777")
										.messageParam(
											MessageParam.builder()
												.receiver(String.valueOf(userVO.getOpenid()))
												.variables(variablesMap)
												.build()
										).build();
									r = messageCenterUtils.sendMessage(request);
									log.info("公众号推送结果:" + JSON.toJSONString(r));
								}

								if(Func.isNotEmpty(userVO.getRegistrationId())){
									contentMap = new HashMap<>(4);
									contentMap.put("title", "保养未完成，已逾期");
									contentMap.put("content", String.format("你有%s个年审梯保养未完成且已逾期，请及时跟进",count));
									contentMap.put("url", "/subpages/workorders/records?type=2&tabIndex=0&statusStr=1,2,3&overdueTypeStr=3&auditTypeStr=2");
									contentMap.put(BladeConstant.MDC_TENANT_ID_KEY, t.getTenantId());
									request = SendRequest.builder()
										.messageTemplateId("1902915055486881794")
										.messageParam(
											MessageParam.builder()
												.receiver(String.valueOf(userVO.getRegistrationId()))
												.variables(contentMap)
												.build()
										).build();
									r = messageCenterUtils.sendMessage(request);
									log.info("APP推送结果:" + JSON.toJSONString(r));
								}
							}
						});
					}
					// 明天即将逾期
					List<ElevatorPlanUserDTO> v2 = planUserDTOS.stream().filter(e -> Func.isNotEmpty(e.getUserId()) && Func.isNotEmpty(e.getOverdueType()) && e.getOverdueType() == 2).collect(Collectors.toList());
					if(Func.isNotEmpty(planUserDTOS)){
						Map<Long,List<ElevatorPlanUserDTO>> map = v2.stream().collect(Collectors.groupingBy(ElevatorPlanUserDTO::getUserId));
						map.forEach((k,v) -> {
							SimpleUserVO userVO = userService.getSimpleUserInfo(k);
							Integer count = v.size();
							if(count > 0){
								Map<String, String> contentMap = new HashMap<>(4);
								contentMap.put("title", "明天超15天逾期");
								contentMap.put("content", String.format("你有%s个年审梯保养未完成，明天即将超15天逾期",count));
								contentMap.put(BladeConstant.MDC_TENANT_ID_KEY, t.getTenantId());
								SendRequest request = SendRequest.builder()
									.messageTemplateId("1902653899365752834")
									.messageParam(
										MessageParam.builder()
											.receiver(String.valueOf(userVO.getUserId()))
											.variables(contentMap)
											.build()
									).build();
								R r = messageCenterUtils.sendMessage(request);
								log.info("梯无忧PC推送结果:" + JSON.toJSONString(r));

								if(Func.isNotEmpty(userVO.getOpenid())){
									contentMap = new HashMap<>(4);
									contentMap.put("phrase4", "保养");
									contentMap.put("phrase5", "明天将逾期");
									contentMap.put("character_string42", String.valueOf(count));
									contentMap.put("time10", DateUtil.now());
									// 构造消息
									String url = "/subpages/workOrders/records?type=2&tabIndex=0&auditTypeStr=2&overdueTypeStr=2";
									Map<String, String> variablesMap = new HashMap<>(4);
									variablesMap.put("content", JSONObject.toJSONString(contentMap));
									variablesMap.put("url", url);
									variablesMap.put(BladeConstant.MDC_TENANT_ID_KEY, t.getTenantId());
									// 维保小程序appid
									variablesMap.put("miniProgramId", "wxb8dc0f5451620604");
									request = SendRequest.builder()
										.messageTemplateId("1902892272744779777")
										.messageParam(
											MessageParam.builder()
												.receiver(String.valueOf(userVO.getOpenid()))
												.variables(variablesMap)
												.build()
										).build();
									r = messageCenterUtils.sendMessage(request);
									log.info("公众号推送结果:" + JSON.toJSONString(r));
								}

								if(Func.isNotEmpty(userVO.getRegistrationId())){
									contentMap = new HashMap<>(4);
									contentMap.put("title", "明天超15天逾期");
									contentMap.put("content", String.format("你有%s个年审梯保养未完成，明天即将超15天逾期",count));
									contentMap.put("url", "/subpages/workorders/records?type=2&tabIndex=0&statusStr=1,2,3&overdueTypeStr=2&auditTypeStr=2");
									contentMap.put(BladeConstant.MDC_TENANT_ID_KEY, t.getTenantId());
									request = SendRequest.builder()
										.messageTemplateId("1902915055486881794")
										.messageParam(
											MessageParam.builder()
												.receiver(String.valueOf(userVO.getRegistrationId()))
												.variables(contentMap)
												.build()
										).build();
									r = messageCenterUtils.sendMessage(request);
									log.info("APP推送结果:" + JSON.toJSONString(r));
								}
							}
						});
					}
				}
			});
			XxlJobHelper.handleSuccess("每天统计用户保养逾期数量发送通知-(countUserByPlanOverdue)-[执行]成功");
		} catch (Exception e) {
			XxlJobHelper.handleSuccess("每天统计用户保养逾期数量发送通知-(countUserByPlanOverdue)-[执行]失败" + e);
		}

	}

	/**
	 * 保养排期合规风险
	 */
	//@Scheduled(cron = "0 0 1 * * ?")
	@XxlJob(value = "countByPlanSchComRisks")
	public void countByPlanSchComRisks(){
		XxlJobHelper.handleSuccess("保养排期合规风险-(countByPlanSchComRisks)-[执行]开始");
		try {
			List<Tenant> tenantList = tenantService.list();
			tenantList.forEach(e -> {
				List<MaintainPlanConfigVO> elevatorList = planConfigService.selectElevatorByPlanSchComRisks(e.getTenantId());
				if(Func.isNotEmpty(elevatorList)){
					long count = elevatorList.stream().filter(t -> t.getNextUserCount() == 1).count();
					if(count > 0){
						List<User> userList = userService.getUserListOfRoleCode("scheduling_elevators", e.getTenantId());
						if(Func.isNotEmpty(userList)){
							String curEnvironment = environment.getActiveProfiles()[0];
							String templateId;
							//当前环境
							if (Func.equalsSafe(curEnvironment, "prod")) {
								// 正式环境
								templateId = "1935243857072590849";
							}else {
								templateId = "1935242753645031425";
							}
							Map<String, String> contentMap = new HashMap<>(4);
							contentMap.put("title", "保养排期人数合规风险");
							contentMap.put("content", String.format("存在%s条年审梯数据，下次计划排期人数存在合规风险。",count));
							contentMap.put(BladeConstant.MDC_TENANT_ID_KEY, e.getTenantId());
							SendRequest request = SendRequest.builder()
								.messageTemplateId(templateId)
								.messageParam(
									MessageParam.builder()
										.receiver(userList.stream().map(u -> String.valueOf(u.getId())).collect(Collectors.joining(",")))
										.variables(contentMap)
										.build()
								).build();
							R r = messageCenterUtils.sendMessage(request);
							log.info("梯无忧PC推送结果:" + JSON.toJSONString(r));
						}
					}
				}
			});
			XxlJobHelper.handleSuccess("保养排期合规风险-(countByPlanSchComRisks)-[执行]成功");
		} catch (Exception e) {
			XxlJobHelper.handleSuccess("保养排期合规风险-(countByPlanSchComRisks)-[执行]失败" + e);
		}
	}

}
